home *** CD-ROM | disk | FTP | other *** search
/ EuroCD 3 / EuroCD 3.iso / Games / Doom / ADoom-0.8 / ADoom_src / p_enemy.c < prev    next >
C/C++ Source or Header  |  1998-06-24  |  37KB  |  2,012 lines

  1. // Emacs style mode select   -*- C++ -*- 
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. //    Enemy thinking, AI.
  21. //    Action Pointer Functions
  22. //    that are associated with states/frames. 
  23. //
  24. //-----------------------------------------------------------------------------
  25.  
  26. static const char
  27. rcsid[] = "$Id: p_enemy.c,v 1.5 1997/02/03 22:45:11 b1 Exp $";
  28.  
  29. #include <stdlib.h>
  30.  
  31. #include "m_random.h"
  32. #include "i_system.h"
  33.  
  34. #include "doomdef.h"
  35. #include "p_local.h"
  36.  
  37. #include "s_sound.h"
  38.  
  39. #include "g_game.h"
  40.  
  41. // State.
  42. #include "doomstat.h"
  43. #include "r_state.h"
  44.  
  45. // Data.
  46. #include "sounds.h"
  47.  
  48.  
  49.  
  50.  
  51. typedef enum
  52. {
  53.     DI_EAST,
  54.     DI_NORTHEAST,
  55.     DI_NORTH,
  56.     DI_NORTHWEST,
  57.     DI_WEST,
  58.     DI_SOUTHWEST,
  59.     DI_SOUTH,
  60.     DI_SOUTHEAST,
  61.     DI_NODIR,
  62.     NUMDIRS
  63.     
  64. } dirtype_t;
  65.  
  66.  
  67. void check_numspechit (char *msg);
  68.  
  69. //
  70. // P_NewChaseDir related LUT.
  71. //
  72. dirtype_t opposite[] =
  73. {
  74.   DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST,
  75.   DI_EAST, DI_NORTHEAST, DI_NORTH, DI_NORTHWEST, DI_NODIR
  76. };
  77.  
  78. dirtype_t diags[] =
  79. {
  80.     DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST
  81. };
  82.  
  83.  
  84.  
  85.  
  86.  
  87. void A_Fall (mobj_t *actor);
  88.  
  89.  
  90. //
  91. // ENEMY THINKING
  92. // Enemies are allways spawned
  93. // with targetplayer = -1, threshold = 0
  94. // Most monsters are spawned unaware of all players,
  95. // but some can be made preaware
  96. //
  97.  
  98.  
  99. //
  100. // Called by P_NoiseAlert.
  101. // Recursively traverse adjacent sectors,
  102. // sound blocking lines cut off traversal.
  103. //
  104.  
  105. mobj_t*        soundtarget;
  106.  
  107. void
  108. P_RecursiveSound
  109. ( sector_t*    sec,
  110.   int        soundblocks )
  111. {
  112.     int        i;
  113.     line_t*    check;
  114.     sector_t*    other;
  115.     
  116.     // wake up all monsters in this sector
  117.     if (sec->validcount == validcount
  118.     && sec->soundtraversed <= soundblocks+1)
  119.     {
  120.     return;        // already flooded
  121.     }
  122.     
  123.     sec->validcount = validcount;
  124.     sec->soundtraversed = soundblocks+1;
  125.     sec->soundtarget = soundtarget;
  126.     
  127.     for (i=0 ;i<sec->linecount ; i++)
  128.     {
  129.     check = sec->lines[i];
  130.     if (! (check->flags & ML_TWOSIDED) )
  131.         continue;
  132.     
  133.     P_LineOpening (check);
  134.  
  135.     if (openrange <= 0)
  136.         continue;    // closed door
  137.     
  138.     if ( sides[ check->sidenum[0] ].sector == sec)
  139.         other = sides[ check->sidenum[1] ] .sector;
  140.     else
  141.         other = sides[ check->sidenum[0] ].sector;
  142.     
  143.     if (check->flags & ML_SOUNDBLOCK)
  144.     {
  145.         if (!soundblocks)
  146.         P_RecursiveSound (other, 1);
  147.     }
  148.     else
  149.         P_RecursiveSound (other, soundblocks);
  150.     }
  151. }
  152.  
  153.  
  154.  
  155. //
  156. // P_NoiseAlert
  157. // If a monster yells at a player,
  158. // it will alert other monsters to the player.
  159. //
  160. void
  161. P_NoiseAlert
  162. ( mobj_t*    target,
  163.   mobj_t*    emmiter )
  164. {
  165.     soundtarget = target;
  166.     validcount++;
  167.     P_RecursiveSound (emmiter->subsector->sector, 0);
  168. }
  169.  
  170.  
  171.  
  172.  
  173. //
  174. // P_CheckMeleeRange
  175. //
  176. boolean P_CheckMeleeRange (mobj_t*    actor)
  177. {
  178.     mobj_t*    pl;
  179.     fixed_t    dist;
  180.     
  181.     if (!actor->target)
  182.     return false;
  183.         
  184.     pl = actor->target;
  185.     dist = P_AproxDistance (pl->x-actor->x, pl->y-actor->y);
  186.  
  187.     if (dist >= MELEERANGE-20*FRACUNIT+pl->info->radius)
  188.     return false;
  189.     
  190.     if (! P_CheckSight (actor, actor->target) )
  191.     return false;
  192.                             
  193.     return true;        
  194. }
  195.  
  196. //
  197. // P_CheckMissileRange
  198. //
  199. boolean P_CheckMissileRange (mobj_t* actor)
  200. {
  201.     fixed_t    dist;
  202.     
  203.     if (! P_CheckSight (actor, actor->target) )
  204.     return false;
  205.     
  206.     if ( actor->flags & MF_JUSTHIT )
  207.     {
  208.     // the target just hit the enemy,
  209.     // so fight back!
  210.     actor->flags &= ~MF_JUSTHIT;
  211.     return true;
  212.     }
  213.     
  214.     if (actor->reactiontime)
  215.     return false;    // do not attack yet
  216.         
  217.     // OPTIMIZE: get this from a global checksight
  218.     dist = P_AproxDistance ( actor->x-actor->target->x,
  219.                  actor->y-actor->target->y) - 64*FRACUNIT;
  220.     
  221.     if (!actor->info->meleestate)
  222.     dist -= 128*FRACUNIT;    // no melee attack, so fire more
  223.  
  224.     dist >>= 16;
  225.  
  226.     if (actor->type == MT_VILE)
  227.     {
  228.     if (dist > 14*64)    
  229.         return false;    // too far away
  230.     }
  231.     
  232.  
  233.     if (actor->type == MT_UNDEAD)
  234.     {
  235.     if (dist < 196)    
  236.         return false;    // close for fist attack
  237.     dist >>= 1;
  238.     }
  239.     
  240.  
  241.     if (actor->type == MT_CYBORG
  242.     || actor->type == MT_SPIDER
  243.     || actor->type == MT_SKULL)
  244.     {
  245.     dist >>= 1;
  246.     }
  247.     
  248.     if (dist > 200)
  249.     dist = 200;
  250.         
  251.     if (actor->type == MT_CYBORG && dist > 160)
  252.     dist = 160;
  253.         
  254.     if (P_Random () < dist)
  255.     return false;
  256.         
  257.     return true;
  258. }
  259.  
  260.  
  261. //
  262. // P_Move
  263. // Move in the current direction,
  264. // returns false if the move is blocked.
  265. //
  266. fixed_t    xspeed[8] = {FRACUNIT,47000,0,-47000,-FRACUNIT,-47000,0,47000};
  267. fixed_t yspeed[8] = {0,47000,FRACUNIT,47000,0,-47000,-FRACUNIT,-47000};
  268.  
  269. #define MAXSPECIALCROSS    8
  270.  
  271. extern    line_t*    spechit[MAXSPECIALCROSS];
  272. extern    int    numspechit;
  273.  
  274. boolean P_Move (mobj_t*    actor)
  275. {
  276.     fixed_t    tryx;
  277.     fixed_t    tryy;
  278.     
  279.     line_t*    ld;
  280.     
  281.     // warning: 'catch', 'throw', and 'try'
  282.     // are all C++ reserved words
  283.     boolean    try_ok;
  284.     boolean    good;
  285.         
  286.     if (actor->movedir == DI_NODIR)
  287.     return false;
  288.         
  289.     if ((unsigned)actor->movedir >= 8)
  290.     I_Error ("Weird actor->movedir!");
  291.         
  292.     tryx = actor->x + actor->info->speed*xspeed[actor->movedir];
  293.     tryy = actor->y + actor->info->speed*yspeed[actor->movedir];
  294.  
  295.     try_ok = P_TryMove (actor, tryx, tryy);
  296.  
  297.     if (!try_ok)
  298.     {
  299.     // open any specials
  300.     if (actor->flags & MF_FLOAT && floatok)
  301.     {
  302.         // must adjust height
  303.         if (actor->z < tmfloorz)
  304.         actor->z += FLOATSPEED;
  305.         else
  306.         actor->z -= FLOATSPEED;
  307.  
  308.         actor->flags |= MF_INFLOAT;
  309.         return true;
  310.     }
  311.         
  312.     if (!numspechit)
  313.         return false;
  314.             
  315.     actor->movedir = DI_NODIR;
  316.     good = false;
  317.     while (numspechit--)
  318.     {
  319.             check_numspechit ("P_Move");
  320.         ld = spechit[numspechit];
  321.         // if the special is not a door
  322.         // that can be opened,
  323.         // return false
  324.         if (P_UseSpecialLine (actor, ld,0))
  325.         good = true;
  326.     }
  327.     return good;
  328.     }
  329.     else
  330.     {
  331.     actor->flags &= ~MF_INFLOAT;
  332.     }
  333.     
  334.     
  335.     if (! (actor->flags & MF_FLOAT) )    
  336.     actor->z = actor->floorz;
  337.     return true; 
  338. }
  339.  
  340.  
  341. //
  342. // TryWalk
  343. // Attempts to move actor on
  344. // in its current (ob->moveangle) direction.
  345. // If blocked by either a wall or an actor
  346. // returns FALSE
  347. // If move is either clear or blocked only by a door,
  348. // returns TRUE and sets...
  349. // If a door is in the way,
  350. // an OpenDoor call is made to start it opening.
  351. //
  352. boolean P_TryWalk (mobj_t* actor)
  353. {    
  354.     if (!P_Move (actor))
  355.     {
  356.     return false;
  357.     }
  358.  
  359.     actor->movecount = P_Random()&15;
  360.     return true;
  361. }
  362.  
  363.  
  364.  
  365.  
  366. void P_NewChaseDir (mobj_t*    actor)
  367. {
  368.     fixed_t    deltax;
  369.     fixed_t    deltay;
  370.     
  371.     dirtype_t    d[3];
  372.     
  373.     int        tdir;
  374.     dirtype_t    olddir;
  375.     
  376.     dirtype_t    turnaround;
  377.  
  378.     if (!actor->target)
  379.     I_Error ("P_NewChaseDir: called with no target");
  380.         
  381.     olddir = actor->movedir;
  382.     turnaround=opposite[olddir];
  383.  
  384.     deltax = actor->target->x - actor->x;
  385.     deltay = actor->target->y - actor->y;
  386.  
  387.     if (deltax>10*FRACUNIT)
  388.     d[1]= DI_EAST;
  389.     else if (deltax<-10*FRACUNIT)
  390.     d[1]= DI_WEST;
  391.     else
  392.     d[1]=DI_NODIR;
  393.  
  394.     if (deltay<-10*FRACUNIT)
  395.     d[2]= DI_SOUTH;
  396.     else if (deltay>10*FRACUNIT)
  397.     d[2]= DI_NORTH;
  398.     else
  399.     d[2]=DI_NODIR;
  400.  
  401.     // try direct route
  402.     if (d[1] != DI_NODIR
  403.     && d[2] != DI_NODIR)
  404.     {
  405.     actor->movedir = diags[((deltay<0)<<1)+(deltax>0)];
  406.     if (actor->movedir != turnaround && P_TryWalk(actor))
  407.         return;
  408.     }
  409.  
  410.     // try other directions
  411.     if (P_Random() > 200
  412.     ||  iabs(deltay)>iabs(deltax))
  413.     {
  414.     tdir=d[1];
  415.     d[1]=d[2];
  416.     d[2]=tdir;
  417.     }
  418.  
  419.     if (d[1]==turnaround)
  420.     d[1]=DI_NODIR;
  421.     if (d[2]==turnaround)
  422.     d[2]=DI_NODIR;
  423.     
  424.     if (d[1]!=DI_NODIR)
  425.     {
  426.     actor->movedir = d[1];
  427.     if (P_TryWalk(actor))
  428.     {
  429.         // either moved forward or attacked
  430.         return;
  431.     }
  432.     }
  433.  
  434.     if (d[2]!=DI_NODIR)
  435.     {
  436.     actor->movedir =d[2];
  437.  
  438.     if (P_TryWalk(actor))
  439.         return;
  440.     }
  441.  
  442.     // there is no direct path to the player,
  443.     // so pick another direction.
  444.     if (olddir!=DI_NODIR)
  445.     {
  446.     actor->movedir =olddir;
  447.  
  448.     if (P_TryWalk(actor))
  449.         return;
  450.     }
  451.  
  452.     // randomly determine direction of search
  453.     if (P_Random()&1)     
  454.     {
  455.     for ( tdir=DI_EAST;
  456.           tdir<=DI_SOUTHEAST;
  457.           tdir++ )
  458.     {
  459.         if (tdir!=turnaround)
  460.         {
  461.         actor->movedir =tdir;
  462.         
  463.         if ( P_TryWalk(actor) )
  464.             return;
  465.         }
  466.     }
  467.     }
  468.     else
  469.     {
  470.     for ( tdir=DI_SOUTHEAST;
  471.           tdir != (DI_EAST-1);
  472.           tdir-- )
  473.     {
  474.         if (tdir!=turnaround)
  475.         {
  476.         actor->movedir =tdir;
  477.         
  478.         if ( P_TryWalk(actor) )
  479.             return;
  480.         }
  481.     }
  482.     }
  483.  
  484.     if (turnaround !=  DI_NODIR)
  485.     {
  486.     actor->movedir =turnaround;
  487.     if ( P_TryWalk(actor) )
  488.         return;
  489.     }
  490.  
  491.     actor->movedir = DI_NODIR;    // can not move
  492. }
  493.  
  494.  
  495.  
  496. //
  497. // P_LookForPlayers
  498. // If allaround is false, only look 180 degrees in front.
  499. // Returns true if a player is targeted.
  500. //
  501. boolean
  502. P_LookForPlayers
  503. ( mobj_t*    actor,
  504.   boolean    allaround )
  505. {
  506.     int        c;
  507.     int        stop;
  508.     player_t*    player;
  509.     sector_t*    sector;
  510.     angle_t    an;
  511.     fixed_t    dist;
  512.         
  513.     sector = actor->subsector->sector;
  514.     
  515.     c = 0;
  516.     stop = (actor->lastlook-1)&3;
  517.     
  518.     for ( ; ; actor->lastlook = (actor->lastlook+1)&3 )
  519.     {
  520.     if (!playeringame[actor->lastlook])
  521.         continue;
  522.             
  523.     if (c++ == 2
  524.         || actor->lastlook == stop)
  525.     {
  526.         // done looking
  527.         return false;    
  528.     }
  529.     
  530.     player = &players[actor->lastlook];
  531.  
  532.     if (player->health <= 0)
  533.         continue;        // dead
  534.  
  535.     if (!P_CheckSight (actor, player->mo))
  536.         continue;        // out of sight
  537.             
  538.     if (!allaround)
  539.     {
  540.         an = R_PointToAngle2 (actor->x,
  541.                   actor->y, 
  542.                   player->mo->x,
  543.                   player->mo->y)
  544.         - actor->angle;
  545.         
  546.         if (an > ANG90 && an < ANG270)
  547.         {
  548.         dist = P_AproxDistance (player->mo->x - actor->x,
  549.                     player->mo->y - actor->y);
  550.         // if real close, react anyway
  551.         if (dist > MELEERANGE)
  552.             continue;    // behind back
  553.         }
  554.     }
  555.         
  556.     actor->target = player->mo;
  557.     return true;
  558.     }
  559.  
  560.     return false;
  561. }
  562.  
  563.  
  564. //
  565. // A_KeenDie
  566. // DOOM II special, map 32.
  567. // Uses special tag 666.
  568. //
  569. void A_KeenDie (mobj_t* mo)
  570. {
  571.     thinker_t*    th;
  572.     mobj_t*    mo2;
  573.     line_t    junk;
  574.  
  575.     A_Fall (mo);
  576.     
  577.     // scan the remaining thinkers
  578.     // to see if all Keens are dead
  579.     for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
  580.     {
  581.     if (th->function.acp1 != (actionf_p1)P_MobjThinker)
  582.         continue;
  583.  
  584.     mo2 = (mobj_t *)th;
  585.     if (mo2 != mo
  586.         && mo2->type == mo->type
  587.         && mo2->health > 0)
  588.     {
  589.         // other Keen not dead
  590.         return;        
  591.     }
  592.     }
  593.  
  594.     junk.tag = 666;
  595.     EV_DoDoor(&junk,open);
  596. }
  597.  
  598.  
  599. //
  600. // ACTION ROUTINES
  601. //
  602.  
  603. //
  604. // A_Look
  605. // Stay in state until a player is sighted.
  606. //
  607. void A_Look (mobj_t* actor)
  608. {
  609.     mobj_t*    targ;
  610.     
  611.     actor->threshold = 0;    // any shot will wake up
  612.     targ = actor->subsector->sector->soundtarget;
  613.  
  614.     if (targ
  615.     && (targ->flags & MF_SHOOTABLE) )
  616.     {
  617.     actor->target = targ;
  618.  
  619.     if ( actor->flags & MF_AMBUSH )
  620.     {
  621.         if (P_CheckSight (actor, actor->target))
  622.         goto seeyou;
  623.     }
  624.     else
  625.         goto seeyou;
  626.     }
  627.     
  628.     
  629.     if (!P_LookForPlayers (actor, false) )
  630.     return;
  631.         
  632.     // go into chase state
  633.   seeyou:
  634.     if (actor->info->seesound)
  635.     {
  636.     int        sound;
  637.         
  638.     switch (actor->info->seesound)
  639.     {
  640.       case sfx_posit1:
  641.       case sfx_posit2:
  642.       case sfx_posit3:
  643.         sound = sfx_posit1+P_Random()%3;
  644.         break;
  645.  
  646.       case sfx_bgsit1:
  647.       case sfx_bgsit2:
  648.         sound = sfx_bgsit1+P_Random()%2;
  649.         break;
  650.  
  651.       default:
  652.         sound = actor->info->seesound;
  653.         break;
  654.     }
  655.  
  656.     if (actor->type==MT_SPIDER
  657.         || actor->type == MT_CYBORG)
  658.     {
  659.         // full volume
  660.         S_StartSound (NULL, sound);
  661.     }
  662.     else
  663.         S_StartSound (actor, sound);
  664.     }
  665.  
  666.     P_SetMobjState (actor, actor->info->seestate);
  667. }
  668.  
  669.  
  670. //
  671. // A_Chase
  672. // Actor has a melee attack,
  673. // so it tries to close as fast as possible
  674. //
  675. void A_Chase (mobj_t*    actor)
  676. {
  677.     int        delta;
  678.  
  679.     if (actor->reactiontime)
  680.     actor->reactiontime--;
  681.                 
  682.  
  683.     // modify target threshold
  684.     if  (actor->threshold)
  685.     {
  686.     if (!actor->target
  687.         || actor->target->health <= 0)
  688.     {
  689.         actor->threshold = 0;
  690.     }
  691.     else
  692.         actor->threshold--;
  693.     }
  694.     
  695.     // turn towards movement direction if not there yet
  696.     if (actor->movedir < 8)
  697.     {
  698.     actor->angle &= (7<<29);
  699.     delta = actor->angle - (actor->movedir << 29);
  700.     
  701.     if (delta > 0)
  702.         actor->angle -= ANG90/2;
  703.     else if (delta < 0)
  704.         actor->angle += ANG90/2;
  705.     }
  706.  
  707.     if (!actor->target
  708.     || !(actor->target->flags&MF_SHOOTABLE))
  709.     {
  710.     // look for a new target
  711.     if (P_LookForPlayers(actor,true))
  712.         return;     // got a new target
  713.     
  714.     P_SetMobjState (actor, actor->info->spawnstate);
  715.     return;
  716.     }
  717.     
  718.     // do not attack twice in a row
  719.     if (actor->flags & MF_JUSTATTACKED)
  720.     {
  721.     actor->flags &= ~MF_JUSTATTACKED;
  722.     if (gameskill != sk_nightmare && !fastparm)
  723.         P_NewChaseDir (actor);
  724.     return;
  725.     }
  726.     
  727.     // check for melee attack
  728.     if (actor->info->meleestate
  729.     && P_CheckMeleeRange (actor))
  730.     {
  731.     if (actor->info->attacksound)
  732.         S_StartSound (actor, actor->info->attacksound);
  733.  
  734.     P_SetMobjState (actor, actor->info->meleestate);
  735.     return;
  736.     }
  737.     
  738.     // check for missile attack
  739.     if (actor->info->missilestate)
  740.     {
  741.     if (gameskill < sk_nightmare
  742.         && !fastparm && actor->movecount)
  743.     {
  744.         goto nomissile;
  745.     }
  746.     
  747.     if (!P_CheckMissileRange (actor))
  748.         goto nomissile;
  749.     
  750.     P_SetMobjState (actor, actor->info->missilestate);
  751.     actor->flags |= MF_JUSTATTACKED;
  752.     return;
  753.     }
  754.  
  755.     // ?
  756.   nomissile:
  757.     // possibly choose another target
  758.     if (netgame
  759.     && !actor->threshold
  760.     && !P_CheckSight (actor, actor->target) )
  761.     {
  762.     if (P_LookForPlayers(actor,true))
  763.         return;    // got a new target
  764.     }
  765.     
  766.     // chase towards player
  767.     if (--actor->movecount<0
  768.     || !P_Move (actor))
  769.     {
  770.     P_NewChaseDir (actor);
  771.     }
  772.     
  773.     // make active sound
  774.     if (actor->info->activesound
  775.     && P_Random () < 3)
  776.     {
  777.     S_StartSound (actor, actor->info->activesound);
  778.     }
  779. }
  780.  
  781.  
  782. //
  783. // A_FaceTarget
  784. //
  785. void A_FaceTarget (mobj_t* actor)
  786. {    
  787.     if (!actor->target)
  788.     return;
  789.     
  790.     actor->flags &= ~MF_AMBUSH;
  791.     
  792.     actor->angle = R_PointToAngle2 (actor->x,
  793.                     actor->y,
  794.                     actor->target->x,
  795.                     actor->target->y);
  796.     
  797.     if (actor->target->flags & MF_SHADOW)
  798.     actor->angle += (P_Random()-P_Random())<<21;
  799. }
  800.  
  801.  
  802. //
  803. // A_PosAttack
  804. //
  805. void A_PosAttack (mobj_t* actor)
  806. {
  807.     int        angle;
  808.     int        damage;
  809.     int        slope;
  810.     
  811.     if (!actor->target)
  812.     return;
  813.         
  814.     A_FaceTarget (actor);
  815.     angle = actor->angle;
  816.     slope = P_AimLineAttack (actor, angle, MISSILERANGE);
  817.  
  818.     S_StartSound (actor, sfx_pistol);
  819.     angle += (P_Random()-P_Random())<<20;
  820.     damage = ((P_Random()%5)+1)*3;
  821.     P_LineAttack (actor, angle, MISSILERANGE, slope, damage);
  822. }
  823.  
  824. void A_SPosAttack (mobj_t* actor)
  825. {
  826.     int        i;
  827.     int        angle;
  828.     int        bangle;
  829.     int        damage;
  830.     int        slope;
  831.     
  832.     if (!actor->target)
  833.     return;
  834.  
  835.     S_StartSound (actor, sfx_shotgn);
  836.     A_FaceTarget (actor);
  837.     bangle = actor->angle;
  838.     slope = P_AimLineAttack (actor, bangle, MISSILERANGE);
  839.  
  840.     for (i=0 ; i<3 ; i++)
  841.     {
  842.     angle = bangle + ((P_Random()-P_Random())<<20);
  843.     damage = ((P_Random()%5)+1)*3;
  844.     P_LineAttack (actor, angle, MISSILERANGE, slope, damage);
  845.     }
  846. }
  847.  
  848. void A_CPosAttack (mobj_t* actor)
  849. {
  850.     int        angle;
  851.     int        bangle;
  852.     int        damage;
  853.     int        slope;
  854.     
  855.     if (!actor->target)
  856.     return;
  857.  
  858.     S_StartSound (actor, sfx_shotgn);
  859.     A_FaceTarget (actor);
  860.     bangle = actor->angle;
  861.     slope = P_AimLineAttack (actor, bangle, MISSILERANGE);
  862.  
  863.     angle = bangle + ((P_Random()-P_Random())<<20);
  864.     damage = ((P_Random()%5)+1)*3;
  865.     P_LineAttack (actor, angle, MISSILERANGE, slope, damage);
  866. }
  867.  
  868. void A_CPosRefire (mobj_t* actor)
  869. {    
  870.     // keep firing unless target got out of sight
  871.     A_FaceTarget (actor);
  872.  
  873.     if (P_Random () < 40)
  874.     return;
  875.  
  876.     if (!actor->target
  877.     || actor->target->health <= 0
  878.     || !P_CheckSight (actor, actor->target) )
  879.     {
  880.     P_SetMobjState (actor, actor->info->seestate);
  881.     }
  882. }
  883.  
  884.  
  885. void A_SpidRefire (mobj_t* actor)
  886. {    
  887.     // keep firing unless target got out of sight
  888.     A_FaceTarget (actor);
  889.  
  890.     if (P_Random () < 10)
  891.     return;
  892.  
  893.     if (!actor->target
  894.     || actor->target->health <= 0
  895.     || !P_CheckSight (actor, actor->target) )
  896.     {
  897.     P_SetMobjState (actor, actor->info->seestate);
  898.     }
  899. }
  900.  
  901. void A_BspiAttack (mobj_t *actor)
  902. {    
  903.     if (!actor->target)
  904.     return;
  905.         
  906.     A_FaceTarget (actor);
  907.  
  908.     // launch a missile
  909.     P_SpawnMissile (actor, actor->target, MT_ARACHPLAZ);
  910. }
  911.  
  912.  
  913. //
  914. // A_TroopAttack
  915. //
  916. void A_TroopAttack (mobj_t* actor)
  917. {
  918.     int        damage;
  919.     
  920.     if (!actor->target)
  921.     return;
  922.         
  923.     A_FaceTarget (actor);
  924.     if (P_CheckMeleeRange (actor))
  925.     {
  926.     S_StartSound (actor, sfx_claw);
  927.     damage = (P_Random()%8+1)*3;
  928.     P_DamageMobj (actor->target, actor, actor, damage);
  929.     return;
  930.     }
  931.  
  932.     
  933.     // launch a missile
  934.     P_SpawnMissile (actor, actor->target, MT_TROOPSHOT);
  935. }
  936.  
  937.  
  938. void A_SargAttack (mobj_t* actor)
  939. {
  940.     int        damage;
  941.  
  942.     if (!actor->target)
  943.     return;
  944.         
  945.     A_FaceTarget (actor);
  946.     if (P_CheckMeleeRange (actor))
  947.     {
  948.     damage = ((P_Random()%10)+1)*4;
  949.     P_DamageMobj (actor->target, actor, actor, damage);
  950.     }
  951. }
  952.  
  953. void A_HeadAttack (mobj_t* actor)
  954. {
  955.     int        damage;
  956.     
  957.     if (!actor->target)
  958.     return;
  959.         
  960.     A_FaceTarget (actor);
  961.     if (P_CheckMeleeRange (actor))
  962.     {
  963.     damage = (P_Random()%6+1)*10;
  964.     P_DamageMobj (actor->target, actor, actor, damage);
  965.     return;
  966.     }
  967.     
  968.     // launch a missile
  969.     P_SpawnMissile (actor, actor->target, MT_HEADSHOT);
  970. }
  971.  
  972. void A_CyberAttack (mobj_t* actor)
  973. {    
  974.     if (!actor->target)
  975.     return;
  976.         
  977.     A_FaceTarget (actor);
  978.     P_SpawnMissile (actor, actor->target, MT_ROCKET);
  979. }
  980.  
  981.  
  982. void A_BruisAttack (mobj_t* actor)
  983. {
  984.     int        damage;
  985.     
  986.     if (!actor->target)
  987.     return;
  988.         
  989.     if (P_CheckMeleeRange (actor))
  990.     {
  991.     S_StartSound (actor, sfx_claw);
  992.     damage = (P_Random()%8+1)*10;
  993.     P_DamageMobj (actor->target, actor, actor, damage);
  994.     return;
  995.     }
  996.     
  997.     // launch a missile
  998.     P_SpawnMissile (actor, actor->target, MT_BRUISERSHOT);
  999. }
  1000.  
  1001.  
  1002. //
  1003. // A_SkelMissile
  1004. //
  1005. void A_SkelMissile (mobj_t* actor)
  1006. {    
  1007.     mobj_t*    mo;
  1008.     
  1009.     if (!actor->target)
  1010.     return;
  1011.         
  1012.     A_FaceTarget (actor);
  1013.     actor->z += 16*FRACUNIT;    // so missile spawns higher
  1014.     mo = P_SpawnMissile (actor, actor->target, MT_TRACER);
  1015.     actor->z -= 16*FRACUNIT;    // back to normal
  1016.  
  1017.     mo->x += mo->momx;
  1018.     mo->y += mo->momy;
  1019.     mo->tracer = actor->target;
  1020. }
  1021.  
  1022. int    TRACEANGLE = 0xc000000;
  1023.  
  1024. void A_Tracer (mobj_t* actor)
  1025. {
  1026.     angle_t    exact;
  1027.     fixed_t    dist;
  1028.     fixed_t    slope;
  1029.     mobj_t*    dest;
  1030.     mobj_t*    th;
  1031.         
  1032.     if (gametic & 3)
  1033.     return;
  1034.     
  1035.     // spawn a puff of smoke behind the rocket        
  1036.     P_SpawnPuff (actor->x, actor->y, actor->z);
  1037.     
  1038.     th = P_SpawnMobj (actor->x-actor->momx,
  1039.               actor->y-actor->momy,
  1040.               actor->z, MT_SMOKE);
  1041.     
  1042.     th->momz = FRACUNIT;
  1043.     th->tics -= P_Random()&3;
  1044.     if (th->tics < 1)
  1045.     th->tics = 1;
  1046.     
  1047.     // adjust direction
  1048.     dest = actor->tracer;
  1049.     
  1050.     if (!dest || dest->health <= 0)
  1051.     return;
  1052.     
  1053.     // change angle    
  1054.     exact = R_PointToAngle2 (actor->x,
  1055.                  actor->y,
  1056.                  dest->x,
  1057.                  dest->y);
  1058.  
  1059.     if (exact != actor->angle)
  1060.     {
  1061.     if (exact - actor->angle > 0x80000000)
  1062.     {
  1063.         actor->angle -= TRACEANGLE;
  1064.         if (exact - actor->angle < 0x80000000)
  1065.         actor->angle = exact;
  1066.     }
  1067.     else
  1068.     {
  1069.         actor->angle += TRACEANGLE;
  1070.         if (exact - actor->angle > 0x80000000)
  1071.         actor->angle = exact;
  1072.     }
  1073.     }
  1074.     
  1075.     exact = actor->angle>>ANGLETOFINESHIFT;
  1076.     actor->momx = FixedMul (actor->info->speed, finecosine[exact]);
  1077.     actor->momy = FixedMul (actor->info->speed, finesine[exact]);
  1078.     
  1079.     // change slope
  1080.     dist = P_AproxDistance (dest->x - actor->x,
  1081.                 dest->y - actor->y);
  1082.     
  1083.     dist = dist / actor->info->speed;
  1084.  
  1085.     if (dist < 1)
  1086.     dist = 1;
  1087.     slope = (dest->z+40*FRACUNIT - actor->z) / dist;
  1088.  
  1089.     if (slope < actor->momz)
  1090.     actor->momz -= FRACUNIT/8;
  1091.     else
  1092.     actor->momz += FRACUNIT/8;
  1093. }
  1094.  
  1095.  
  1096. void A_SkelWhoosh (mobj_t*    actor)
  1097. {
  1098.     if (!actor->target)
  1099.     return;
  1100.     A_FaceTarget (actor);
  1101.     S_StartSound (actor,sfx_skeswg);
  1102. }
  1103.  
  1104. void A_SkelFist (mobj_t*    actor)
  1105. {
  1106.     int        damage;
  1107.  
  1108.     if (!actor->target)
  1109.     return;
  1110.         
  1111.     A_FaceTarget (actor);
  1112.     
  1113.     if (P_CheckMeleeRange (actor))
  1114.     {
  1115.     damage = ((P_Random()%10)+1)*6;
  1116.     S_StartSound (actor, sfx_skepch);
  1117.     P_DamageMobj (actor->target, actor, actor, damage);
  1118.     }
  1119. }
  1120.  
  1121.  
  1122.  
  1123. //
  1124. // PIT_VileCheck
  1125. // Detect a corpse that could be raised.
  1126. //
  1127. mobj_t*        corpsehit;
  1128. mobj_t*        vileobj;
  1129. fixed_t        viletryx;
  1130. fixed_t        viletryy;
  1131.  
  1132. boolean PIT_VileCheck (mobj_t*    thing)
  1133. {
  1134.     int        maxdist;
  1135.     boolean    check;
  1136.     
  1137.     if (!(thing->flags & MF_CORPSE) )
  1138.     return true;    // not a monster
  1139.     
  1140.     if (thing->tics != -1)
  1141.     return true;    // not lying still yet
  1142.     
  1143.     if (thing->info->raisestate == S_NULL)
  1144.     return true;    // monster doesn't have a raise state
  1145.     
  1146.     maxdist = thing->info->radius + mobjinfo[MT_VILE].radius;
  1147.     
  1148.     if ( iabs(thing->x - viletryx) > maxdist
  1149.      || iabs(thing->y - viletryy) > maxdist )
  1150.     return true;        // not actually touching
  1151.         
  1152.     corpsehit = thing;
  1153.     corpsehit->momx = corpsehit->momy = 0;
  1154.     corpsehit->height <<= 2;
  1155.     check = P_CheckPosition (corpsehit, corpsehit->x, corpsehit->y);
  1156.     corpsehit->height >>= 2;
  1157.  
  1158.     if (!check)
  1159.     return true;        // doesn't fit here
  1160.         
  1161.     return false;        // got one, so stop checking
  1162. }
  1163.  
  1164.  
  1165.  
  1166. //
  1167. // A_VileChase
  1168. // Check for ressurecting a body
  1169. //
  1170. void A_VileChase (mobj_t* actor)
  1171. {
  1172.     int            xl;
  1173.     int            xh;
  1174.     int            yl;
  1175.     int            yh;
  1176.     
  1177.     int            bx;
  1178.     int            by;
  1179.  
  1180.     mobjinfo_t*        info;
  1181.     mobj_t*        temp;
  1182.     
  1183.     if (actor->movedir != DI_NODIR)
  1184.     {
  1185.     // check for corpses to raise
  1186.     viletryx =
  1187.         actor->x + actor->info->speed*xspeed[actor->movedir];
  1188.     viletryy =
  1189.         actor->y + actor->info->speed*yspeed[actor->movedir];
  1190.  
  1191.     xl = (viletryx - bmaporgx - MAXRADIUS*2)>>MAPBLOCKSHIFT;
  1192.     xh = (viletryx - bmaporgx + MAXRADIUS*2)>>MAPBLOCKSHIFT;
  1193.     yl = (viletryy - bmaporgy - MAXRADIUS*2)>>MAPBLOCKSHIFT;
  1194.     yh = (viletryy - bmaporgy + MAXRADIUS*2)>>MAPBLOCKSHIFT;
  1195.     
  1196.     vileobj = actor;
  1197.     for (bx=xl ; bx<=xh ; bx++)
  1198.     {
  1199.         for (by=yl ; by<=yh ; by++)
  1200.         {
  1201.         // Call PIT_VileCheck to check
  1202.         // whether object is a corpse
  1203.         // that canbe raised.
  1204.         if (!P_BlockThingsIterator(bx,by,PIT_VileCheck))
  1205.         {
  1206.             // got one!
  1207.             temp = actor->target;
  1208.             actor->target = corpsehit;
  1209.             A_FaceTarget (actor);
  1210.             actor->target = temp;
  1211.                     
  1212.             P_SetMobjState (actor, S_VILE_HEAL1);
  1213.             S_StartSound (corpsehit, sfx_slop);
  1214.             info = corpsehit->info;
  1215.             
  1216.             P_SetMobjState (corpsehit,info->raisestate);
  1217.             corpsehit->height <<= 2;
  1218.             corpsehit->flags = info->flags;
  1219.             corpsehit->health = info->spawnhealth;
  1220.             corpsehit->target = NULL;
  1221.  
  1222.             return;
  1223.         }
  1224.         }
  1225.     }
  1226.     }
  1227.  
  1228.     // Return to normal attack.
  1229.     A_Chase (actor);
  1230. }
  1231.  
  1232.  
  1233. //
  1234. // A_VileStart
  1235. //
  1236. void A_VileStart (mobj_t* actor)
  1237. {
  1238.     S_StartSound (actor, sfx_vilatk);
  1239. }
  1240.  
  1241.  
  1242. //
  1243. // A_Fire
  1244. // Keep fire in front of player unless out of sight
  1245. //
  1246. void A_Fire (mobj_t* actor);
  1247.  
  1248. void A_StartFire (mobj_t* actor)
  1249. {
  1250.     S_StartSound(actor,sfx_flamst);
  1251.     A_Fire(actor);
  1252. }
  1253.  
  1254. void A_FireCrackle (mobj_t* actor)
  1255. {
  1256.     S_StartSound(actor,sfx_flame);
  1257.     A_Fire(actor);
  1258. }
  1259.  
  1260. void A_Fire (mobj_t* actor)
  1261. {
  1262.     mobj_t*    dest;
  1263.     unsigned    an;
  1264.         
  1265.     dest = actor->tracer;
  1266.     if (!dest)
  1267.     return;
  1268.         
  1269.     // don't move it if the vile lost sight
  1270.     if (!P_CheckSight (actor->target, dest) )
  1271.     return;
  1272.  
  1273.     an = dest->angle >> ANGLETOFINESHIFT;
  1274.  
  1275.     P_UnsetThingPosition (actor);
  1276.     actor->x = dest->x + FixedMul (24*FRACUNIT, finecosine[an]);
  1277.     actor->y = dest->y + FixedMul (24*FRACUNIT, finesine[an]);
  1278.     actor->z = dest->z;
  1279.     P_SetThingPosition (actor);
  1280. }
  1281.  
  1282.  
  1283.  
  1284. //
  1285. // A_VileTarget
  1286. // Spawn the hellfire
  1287. //
  1288. void A_VileTarget (mobj_t*    actor)
  1289. {
  1290.     mobj_t*    fog;
  1291.     
  1292.     if (!actor->target)
  1293.     return;
  1294.  
  1295.     A_FaceTarget (actor);
  1296.  
  1297.     fog = P_SpawnMobj (actor->target->x,
  1298.                actor->target->x,
  1299.                actor->target->z, MT_FIRE);
  1300.     
  1301.     actor->tracer = fog;
  1302.     fog->target = actor;
  1303.     fog->tracer = actor->target;
  1304.     A_Fire (fog);
  1305. }
  1306.  
  1307.  
  1308.  
  1309.  
  1310. //
  1311. // A_VileAttack
  1312. //
  1313. void A_VileAttack (mobj_t* actor)
  1314. {    
  1315.     mobj_t*    fire;
  1316.     int        an;
  1317.     
  1318.     if (!actor->target)
  1319.     return;
  1320.     
  1321.     A_FaceTarget (actor);
  1322.  
  1323.     if (!P_CheckSight (actor, actor->target) )
  1324.     return;
  1325.  
  1326.     S_StartSound (actor, sfx_barexp);
  1327.     P_DamageMobj (actor->target, actor, actor, 20);
  1328.     actor->target->momz = 1000*FRACUNIT/actor->target->info->mass;
  1329.     
  1330.     an = actor->angle >> ANGLETOFINESHIFT;
  1331.  
  1332.     fire = actor->tracer;
  1333.  
  1334.     if (!fire)
  1335.     return;
  1336.         
  1337.     // move the fire between the vile and the player
  1338.     fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]);
  1339.     fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]);    
  1340.     P_RadiusAttack (fire, actor, 70 );
  1341. }
  1342.  
  1343.  
  1344.  
  1345.  
  1346. //
  1347. // Mancubus attack,
  1348. // firing three missiles (bruisers)
  1349. // in three different directions?
  1350. // Doesn't look like it. 
  1351. //
  1352. #define    FATSPREAD    (ANG90/8)
  1353.  
  1354. void A_FatRaise (mobj_t *actor)
  1355. {
  1356.     A_FaceTarget (actor);
  1357.     S_StartSound (actor, sfx_manatk);
  1358. }
  1359.  
  1360.  
  1361. void A_FatAttack1 (mobj_t* actor)
  1362. {
  1363.     mobj_t*    mo;
  1364.     int        an;
  1365.     
  1366.     A_FaceTarget (actor);
  1367.     // Change direction  to ...
  1368.     actor->angle += FATSPREAD;
  1369.     P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1370.  
  1371.     mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1372.     mo->angle += FATSPREAD;
  1373.     an = mo->angle >> ANGLETOFINESHIFT;
  1374.     mo->momx = FixedMul (mo->info->speed, finecosine[an]);
  1375.     mo->momy = FixedMul (mo->info->speed, finesine[an]);
  1376. }
  1377.  
  1378. void A_FatAttack2 (mobj_t* actor)
  1379. {
  1380.     mobj_t*    mo;
  1381.     int        an;
  1382.  
  1383.     A_FaceTarget (actor);
  1384.     // Now here choose opposite deviation.
  1385.     actor->angle -= FATSPREAD;
  1386.     P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1387.  
  1388.     mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1389.     mo->angle -= FATSPREAD*2;
  1390.     an = mo->angle >> ANGLETOFINESHIFT;
  1391.     mo->momx = FixedMul (mo->info->speed, finecosine[an]);
  1392.     mo->momy = FixedMul (mo->info->speed, finesine[an]);
  1393. }
  1394.  
  1395. void A_FatAttack3 (mobj_t*    actor)
  1396. {
  1397.     mobj_t*    mo;
  1398.     int        an;
  1399.  
  1400.     A_FaceTarget (actor);
  1401.     
  1402.     mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1403.     mo->angle -= FATSPREAD/2;
  1404.     an = mo->angle >> ANGLETOFINESHIFT;
  1405.     mo->momx = FixedMul (mo->info->speed, finecosine[an]);
  1406.     mo->momy = FixedMul (mo->info->speed, finesine[an]);
  1407.  
  1408.     mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1409.     mo->angle += FATSPREAD/2;
  1410.     an = mo->angle >> ANGLETOFINESHIFT;
  1411.     mo->momx = FixedMul (mo->info->speed, finecosine[an]);
  1412.     mo->momy = FixedMul (mo->info->speed, finesine[an]);
  1413. }
  1414.  
  1415.  
  1416. //
  1417. // SkullAttack
  1418. // Fly at the player like a missile.
  1419. //
  1420. #define    SKULLSPEED        (20*FRACUNIT)
  1421.  
  1422. void A_SkullAttack (mobj_t* actor)
  1423. {
  1424.     mobj_t*        dest;
  1425.     angle_t        an;
  1426.     int            dist;
  1427.  
  1428.     if (!actor->target)
  1429.     return;
  1430.         
  1431.     dest = actor->target;    
  1432.     actor->flags |= MF_SKULLFLY;
  1433.  
  1434.     S_StartSound (actor, actor->info->attacksound);
  1435.     A_FaceTarget (actor);
  1436.     an = actor->angle >> ANGLETOFINESHIFT;
  1437.     actor->momx = FixedMul (SKULLSPEED, finecosine[an]);
  1438.     actor->momy = FixedMul (SKULLSPEED, finesine[an]);
  1439.     dist = P_AproxDistance (dest->x - actor->x, dest->y - actor->y);
  1440.     dist = dist / SKULLSPEED;
  1441.     
  1442.     if (dist < 1)
  1443.     dist = 1;
  1444.     actor->momz = (dest->z+(dest->height>>1) - actor->z) / dist;
  1445. }
  1446.  
  1447.  
  1448. //
  1449. // A_PainShootSkull
  1450. // Spawn a lost soul and launch it at the target
  1451. //
  1452. void
  1453. A_PainShootSkull
  1454. ( mobj_t*    actor,
  1455.   angle_t    angle )
  1456. {
  1457.     fixed_t    x;
  1458.     fixed_t    y;
  1459.     fixed_t    z;
  1460.     
  1461.     mobj_t*    newmobj;
  1462.     angle_t    an;
  1463.     int        prestep;
  1464.     int        count;
  1465.     thinker_t*    currentthinker;
  1466.  
  1467.     // count total number of skull currently on the level
  1468.     count = 0;
  1469.  
  1470.     currentthinker = thinkercap.next;
  1471.     while (currentthinker != &thinkercap)
  1472.     {
  1473.     if (   (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
  1474.         && ((mobj_t *)currentthinker)->type == MT_SKULL)
  1475.         count++;
  1476.     currentthinker = currentthinker->next;
  1477.     }
  1478.  
  1479.     // if there are allready 20 skulls on the level,
  1480.     // don't spit another one
  1481.     if (count > 20)
  1482.     return;
  1483.  
  1484.  
  1485.     // okay, there's playe for another one
  1486.     an = angle >> ANGLETOFINESHIFT;
  1487.     
  1488.     prestep =
  1489.     4*FRACUNIT
  1490.     + 3*(actor->info->radius + mobjinfo[MT_SKULL].radius)/2;
  1491.     
  1492.     x = actor->x + FixedMul (prestep, finecosine[an]);
  1493.     y = actor->y + FixedMul (prestep, finesine[an]);
  1494.     z = actor->z + 8*FRACUNIT;
  1495.         
  1496.     newmobj = P_SpawnMobj (x , y, z, MT_SKULL);
  1497.  
  1498.     // Check for movements.
  1499.     if (!P_TryMove (newmobj, newmobj->x, newmobj->y))
  1500.     {
  1501.     // kill it immediately
  1502.     P_DamageMobj (newmobj,actor,actor,10000);    
  1503.     return;
  1504.     }
  1505.         
  1506.     newmobj->target = actor->target;
  1507.     A_SkullAttack (newmobj);
  1508. }
  1509.  
  1510.  
  1511. //
  1512. // A_PainAttack
  1513. // Spawn a lost soul and launch it at the target
  1514. // 
  1515. void A_PainAttack (mobj_t* actor)
  1516. {
  1517.     if (!actor->target)
  1518.     return;
  1519.  
  1520.     A_FaceTarget (actor);
  1521.     A_PainShootSkull (actor, actor->angle);
  1522. }
  1523.  
  1524.  
  1525. void A_PainDie (mobj_t* actor)
  1526. {
  1527.     A_Fall (actor);
  1528.     A_PainShootSkull (actor, actor->angle+ANG90);
  1529.     A_PainShootSkull (actor, actor->angle+ANG180);
  1530.     A_PainShootSkull (actor, actor->angle+ANG270);
  1531. }
  1532.  
  1533.  
  1534.  
  1535.  
  1536.  
  1537.  
  1538. void A_Scream (mobj_t* actor)
  1539. {
  1540.     int        sound;
  1541.     
  1542.     switch (actor->info->deathsound)
  1543.     {
  1544.       case 0:
  1545.     return;
  1546.         
  1547.       case sfx_podth1:
  1548.       case sfx_podth2:
  1549.       case sfx_podth3:
  1550.     sound = sfx_podth1 + P_Random ()%3;
  1551.     break;
  1552.         
  1553.       case sfx_bgdth1:
  1554.       case sfx_bgdth2:
  1555.     sound = sfx_bgdth1 + P_Random ()%2;
  1556.     break;
  1557.     
  1558.       default:
  1559.     sound = actor->info->deathsound;
  1560.     break;
  1561.     }
  1562.  
  1563.     // Check for bosses.
  1564.     if (actor->type==MT_SPIDER
  1565.     || actor->type == MT_CYBORG)
  1566.     {
  1567.     // full volume
  1568.     S_StartSound (NULL, sound);
  1569.     }
  1570.     else
  1571.     S_StartSound (actor, sound);
  1572. }
  1573.  
  1574.  
  1575. void A_XScream (mobj_t* actor)
  1576. {
  1577.     S_StartSound (actor, sfx_slop);    
  1578. }
  1579.  
  1580. void A_Pain (mobj_t* actor)
  1581. {
  1582.     if (actor->info->painsound)
  1583.     S_StartSound (actor, actor->info->painsound);    
  1584. }
  1585.  
  1586.  
  1587.  
  1588. void A_Fall (mobj_t *actor)
  1589. {
  1590.     // actor is on ground, it can be walked over
  1591.     actor->flags &= ~MF_SOLID;
  1592.  
  1593.     // So change this if corpse objects
  1594.     // are meant to be obstacles.
  1595. }
  1596.  
  1597.  
  1598. //
  1599. // A_Explode
  1600. //
  1601. void A_Explode (mobj_t* thingy)
  1602. {
  1603.     P_RadiusAttack ( thingy, thingy->target, 128 );
  1604. }
  1605.  
  1606.  
  1607. //
  1608. // A_BossDeath
  1609. // Possibly trigger special effects
  1610. // if on first boss level
  1611. //
  1612. void A_BossDeath (mobj_t* mo)
  1613. {
  1614.     thinker_t*    th;
  1615.     mobj_t*    mo2;
  1616.     line_t    junk;
  1617.     int        i;
  1618.         
  1619.     if ( gamemode == commercial)
  1620.     {
  1621.     if (gamemap != 7)
  1622.         return;
  1623.         
  1624.     if ((mo->type != MT_FATSO)
  1625.         && (mo->type != MT_BABY))
  1626.         return;
  1627.     }
  1628.     else
  1629.     {
  1630.     switch(gameepisode)
  1631.     {
  1632.       case 1:
  1633.         if (gamemap != 8)
  1634.         return;
  1635.  
  1636.         if (mo->type != MT_BRUISER)
  1637.         return;
  1638.         break;
  1639.         
  1640.       case 2:
  1641.         if (gamemap != 8)
  1642.         return;
  1643.  
  1644.         if (mo->type != MT_CYBORG)
  1645.         return;
  1646.         break;
  1647.         
  1648.       case 3:
  1649.         if (gamemap != 8)
  1650.         return;
  1651.         
  1652.         if (mo->type != MT_SPIDER)
  1653.         return;
  1654.         
  1655.         break;
  1656.         
  1657.       case 4:
  1658.         switch(gamemap)
  1659.         {
  1660.           case 6:
  1661.         if (mo->type != MT_CYBORG)
  1662.             return;
  1663.         break;
  1664.         
  1665.           case 8: 
  1666.         if (mo->type != MT_SPIDER)
  1667.             return;
  1668.         break;
  1669.         
  1670.           default:
  1671.         return;
  1672.         break;
  1673.         }
  1674.         break;
  1675.         
  1676.       default:
  1677.         if (gamemap != 8)
  1678.         return;
  1679.         break;
  1680.     }
  1681.         
  1682.     }
  1683.  
  1684.     
  1685.     // make sure there is a player alive for victory
  1686.     for (i=0 ; i<MAXPLAYERS ; i++)
  1687.     if (playeringame[i] && players[i].health > 0)
  1688.         break;
  1689.     
  1690.     if (i==MAXPLAYERS)
  1691.     return;    // no one left alive, so do not end game
  1692.     
  1693.     // scan the remaining thinkers to see
  1694.     // if all bosses are dead
  1695.     for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
  1696.     {
  1697.     if (th->function.acp1 != (actionf_p1)P_MobjThinker)
  1698.         continue;
  1699.     
  1700.     mo2 = (mobj_t *)th;
  1701.     if (mo2 != mo
  1702.         && mo2->type == mo->type
  1703.         && mo2->health > 0)
  1704.     {
  1705.         // other boss not dead
  1706.         return;
  1707.     }
  1708.     }
  1709.     
  1710.     // victory!
  1711.     if ( gamemode == commercial)
  1712.     {
  1713.     if (gamemap == 7)
  1714.     {
  1715.         if (mo->type == MT_FATSO)
  1716.         {
  1717.         junk.tag = 666;
  1718.         EV_DoFloor(&junk,lowerFloorToLowest);
  1719.         return;
  1720.         }
  1721.         
  1722.         if (mo->type == MT_BABY)
  1723.         {
  1724.         junk.tag = 667;
  1725.         EV_DoFloor(&junk,raiseToTexture);
  1726.         return;
  1727.         }
  1728.     }
  1729.     }
  1730.     else
  1731.     {
  1732.     switch(gameepisode)
  1733.     {
  1734.       case 1:
  1735.         junk.tag = 666;
  1736.         EV_DoFloor (&junk, lowerFloorToLowest);
  1737.         return;
  1738.         break;
  1739.         
  1740.       case 4:
  1741.         switch(gamemap)
  1742.         {
  1743.           case 6:
  1744.         junk.tag = 666;
  1745.         EV_DoDoor (&junk, blazeOpen);
  1746.         return;
  1747.         break;
  1748.         
  1749.           case 8:
  1750.         junk.tag = 666;
  1751.         EV_DoFloor (&junk, lowerFloorToLowest);
  1752.         return;
  1753.         break;
  1754.         }
  1755.     }
  1756.     }
  1757.     
  1758.     G_ExitLevel ();
  1759. }
  1760.  
  1761.  
  1762. void A_Hoof (mobj_t* mo)
  1763. {
  1764.     S_StartSound (mo, sfx_hoof);
  1765.     A_Chase (mo);
  1766. }
  1767.  
  1768. void A_Metal (mobj_t* mo)
  1769. {
  1770.     S_StartSound (mo, sfx_metal);
  1771.     A_Chase (mo);
  1772. }
  1773.  
  1774. void A_BabyMetal (mobj_t* mo)
  1775. {
  1776.     S_StartSound (mo, sfx_bspwlk);
  1777.     A_Chase (mo);
  1778. }
  1779.  
  1780. void
  1781. A_OpenShotgun2
  1782. ( player_t*    player,
  1783.   pspdef_t*    psp )
  1784. {
  1785.     S_StartSound (player->mo, sfx_dbopn);
  1786. }
  1787.  
  1788. void
  1789. A_LoadShotgun2
  1790. ( player_t*    player,
  1791.   pspdef_t*    psp )
  1792. {
  1793.     S_StartSound (player->mo, sfx_dbload);
  1794. }
  1795.  
  1796. void
  1797. A_ReFire
  1798. ( player_t*    player,
  1799.   pspdef_t*    psp );
  1800.  
  1801. void
  1802. A_CloseShotgun2
  1803. ( player_t*    player,
  1804.   pspdef_t*    psp )
  1805. {
  1806.     S_StartSound (player->mo, sfx_dbcls);
  1807.     A_ReFire(player,psp);
  1808. }
  1809.  
  1810.  
  1811.  
  1812. mobj_t*        braintargets[32];
  1813. int        numbraintargets;
  1814. int        braintargeton;
  1815.  
  1816. void A_BrainAwake (mobj_t* mo)
  1817. {
  1818.     thinker_t*    thinker;
  1819.     mobj_t*    m;
  1820.     
  1821.     // find all the target spots
  1822.     numbraintargets = 0;
  1823.     braintargeton = 0;
  1824.     
  1825.     thinker = thinkercap.next;
  1826.     for (thinker = thinkercap.next ;
  1827.      thinker != &thinkercap ;
  1828.      thinker = thinker->next)
  1829.     {
  1830.     if (thinker->function.acp1 != (actionf_p1)P_MobjThinker)
  1831.         continue;    // not a mobj
  1832.  
  1833.     m = (mobj_t *)thinker;
  1834.  
  1835.     if (m->type == MT_BOSSTARGET )
  1836.     {
  1837.         braintargets[numbraintargets] = m;
  1838.         numbraintargets++;
  1839.     }
  1840.     }
  1841.     
  1842.     S_StartSound (NULL,sfx_bossit);
  1843. }
  1844.  
  1845.  
  1846. void A_BrainPain (mobj_t*    mo)
  1847. {
  1848.     S_StartSound (NULL,sfx_bospn);
  1849. }
  1850.  
  1851.  
  1852. void A_BrainScream (mobj_t*    mo)
  1853. {
  1854.     int        x;
  1855.     int        y;
  1856.     int        z;
  1857.     mobj_t*    th;
  1858.     
  1859.     for (x=mo->x - 196*FRACUNIT ; x< mo->x + 320*FRACUNIT ; x+= FRACUNIT*8)
  1860.     {
  1861.     y = mo->y - 320*FRACUNIT;
  1862.     z = 128 + P_Random()*2*FRACUNIT;
  1863.     th = P_SpawnMobj (x,y,z, MT_ROCKET);
  1864.     th->momz = P_Random()*512;
  1865.  
  1866.     P_SetMobjState (th, S_BRAINEXPLODE1);
  1867.  
  1868.     th->tics -= P_Random()&7;
  1869.     if (th->tics < 1)
  1870.         th->tics = 1;
  1871.     }
  1872.     
  1873.     S_StartSound (NULL,sfx_bosdth);
  1874. }
  1875.  
  1876.  
  1877.  
  1878. void A_BrainExplode (mobj_t* mo)
  1879. {
  1880.     int        x;
  1881.     int        y;
  1882.     int        z;
  1883.     mobj_t*    th;
  1884.     
  1885.     x = mo->x + (P_Random () - P_Random ())*2048;
  1886.     y = mo->y;
  1887.     z = 128 + P_Random()*2*FRACUNIT;
  1888.     th = P_SpawnMobj (x,y,z, MT_ROCKET);
  1889.     th->momz = P_Random()*512;
  1890.  
  1891.     P_SetMobjState (th, S_BRAINEXPLODE1);
  1892.  
  1893.     th->tics -= P_Random()&7;
  1894.     if (th->tics < 1)
  1895.     th->tics = 1;
  1896. }
  1897.  
  1898.  
  1899. void A_BrainDie (mobj_t*    mo)
  1900. {
  1901.     G_ExitLevel ();
  1902. }
  1903.  
  1904. void A_BrainSpit (mobj_t*    mo)
  1905. {
  1906.     mobj_t*    targ;
  1907.     mobj_t*    newmobj;
  1908.     
  1909.     static int    easy = 0;
  1910.     
  1911.     easy ^= 1;
  1912.     if (gameskill <= sk_easy && (!easy))
  1913.     return;
  1914.         
  1915.     // shoot a cube at current target
  1916.     targ = braintargets[braintargeton];
  1917.     braintargeton = (braintargeton+1)%numbraintargets;
  1918.  
  1919.     // spawn brain missile
  1920.     newmobj = P_SpawnMissile (mo, targ, MT_SPAWNSHOT);
  1921.     newmobj->target = targ;
  1922.     newmobj->reactiontime =
  1923.     ((targ->y - mo->y)/newmobj->momy) / newmobj->state->tics;
  1924.  
  1925.     S_StartSound(NULL, sfx_bospit);
  1926. }
  1927.  
  1928.  
  1929.  
  1930. void A_SpawnFly (mobj_t* mo);
  1931.  
  1932. // travelling cube sound
  1933. void A_SpawnSound (mobj_t* mo)    
  1934. {
  1935.     S_StartSound (mo,sfx_boscub);
  1936.     A_SpawnFly(mo);
  1937. }
  1938.  
  1939. void A_SpawnFly (mobj_t* mo)
  1940. {
  1941.     mobj_t*    newmobj;
  1942.     mobj_t*    fog;
  1943.     mobj_t*    targ;
  1944.     int        r;
  1945.     mobjtype_t    type;
  1946.     
  1947.     if (--mo->reactiontime)
  1948.     return;    // still flying
  1949.     
  1950.     targ = mo->target;
  1951.  
  1952.     // First spawn teleport fog.
  1953.     fog = P_SpawnMobj (targ->x, targ->y, targ->z, MT_SPAWNFIRE);
  1954.     S_StartSound (fog, sfx_telept);
  1955.  
  1956.     // Randomly select monster to spawn.
  1957.     r = P_Random ();
  1958.  
  1959.     // Probability distribution (kind of :),
  1960.     // decreasing likelihood.
  1961.     if ( r<50 )
  1962.     type = MT_TROOP;
  1963.     else if (r<90)
  1964.     type = MT_SERGEANT;
  1965.     else if (r<120)
  1966.     type = MT_SHADOWS;
  1967.     else if (r<130)
  1968.     type = MT_PAIN;
  1969.     else if (r<160)
  1970.     type = MT_HEAD;
  1971.     else if (r<162)
  1972.     type = MT_VILE;
  1973.     else if (r<172)
  1974.     type = MT_UNDEAD;
  1975.     else if (r<192)
  1976.     type = MT_BABY;
  1977.     else if (r<222)
  1978.     type = MT_FATSO;
  1979.     else if (r<246)
  1980.     type = MT_KNIGHT;
  1981.     else
  1982.     type = MT_BRUISER;        
  1983.  
  1984.     newmobj    = P_SpawnMobj (targ->x, targ->y, targ->z, type);
  1985.     if (P_LookForPlayers (newmobj, true) )
  1986.     P_SetMobjState (newmobj, newmobj->info->seestate);
  1987.     
  1988.     // telefrag anything in this spot
  1989.     P_TeleportMove (newmobj, newmobj->x, newmobj->y);
  1990.  
  1991.     // remove self (i.e., cube).
  1992.     P_RemoveMobj (mo);
  1993. }
  1994.  
  1995.  
  1996.  
  1997. void A_PlayerScream (mobj_t* mo)
  1998. {
  1999.     // Default death sound.
  2000.     int        sound = sfx_pldeth;
  2001.     
  2002.     if ( (gamemode == commercial)
  2003.     &&     (mo->health < -50))
  2004.     {
  2005.     // IF THE PLAYER DIES
  2006.     // LESS THAN -50% WITHOUT GIBBING
  2007.     sound = sfx_pdiehi;
  2008.     }
  2009.     
  2010.     S_StartSound (mo, sound);
  2011. }
  2012.